VPC LambdaからVPCエンドポイント経由でDynamoDBにアクセスしてみた
サーバーレス開発部改め、CX事業本部の佐藤です。
概要
VPC LambdaからDynamoDBにアクセスするユースケースがあったため、実際にやってみました。
VPCにあるRDSなどにアクセスする際は、VPC Lambdaにする必要があります。VPC Lambdaにした場合はLambdaのインターネットアクセスが失われるため、VPC以外のAWSリソースにはアクセスできません(DynamoDBなど)。VPC Lambdaがインターネットにアクセスする際は、AWSの制約でLambdaをプライベートサブネットに配置し、パブリックサブネットにNAT ゲートウェイを配置する必要があります。
https://aws.amazon.com/jp/premiumsupport/knowledge-center/internet-access-lambda-function/
以前は、VPC LambdaからDynamoDBなどにアクセスする際は、この記事のようにNATゲートウェイを配置する必要があったんですが、VPC エンドポイントがDynamoDBに対応したため、VPCエンドポイント経由でアクセスすることが可能になりました。
https://aws.amazon.com/jp/blogs/news/new-vpc-endpoints-for-dynamodb/
実際に動かしていきたいと思います。
VPC、プライベートサブネット、セキュリティグループを作成する
VPCとプライベートサブネット、セキュリティーグループを作成します。マネージメントコンソールやCloudFormationで作成できます。今回は、CloudFormationで作成していきます。テスト用のDynamoDBテーブルも一緒に作成しています。
以下の内容でスタックを作成します。
AWSTemplateFormatVersion: 2010-09-09 Description: "Create VPC" Resources: VPC: Type: AWS::EC2::VPC Properties: CidrBlock: 10.0.0.0/16 EnableDnsSupport: 'true' EnableDnsHostnames: 'true' InstanceTenancy: default Tags: - Key: Name Value: "blog" PrivateSubnetA: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC CidrBlock: 10.0.0.0/24 AvailabilityZone: ap-northeast-1a Tags: - Key: Name Value: "Private Subnet A" PrivateSubnetC: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC CidrBlock: 10.0.1.0/24 AvailabilityZone: ap-northeast-1c Tags: - Key: Name Value: "Private Subnet C" VPCPrivateRouteTable: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref VPC VPCPrivateSubnetARouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref PrivateSubnetA RouteTableId: !Ref VPCPrivateRouteTable VPCPrivateSubnetCRouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref PrivateSubnetC RouteTableId: !Ref VPCPrivateRouteTable LambdaSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Lambda Security Group VpcId: !Ref VPC BlogTestTable: Type: "AWS::DynamoDB::Table" Properties: AttributeDefinitions: - AttributeName: "id" AttributeType: "N" KeySchema: - AttributeName: "id" KeyType: "HASH" BillingMode: PAY_PER_REQUEST
CLIでスタックを作成します
aws cloudformation create-stack --stack-name 任意のスタック名 --template-body file://上記の保存したファイル名
VPC Lambdaを作成する
テスト用のVPC Lambdaを作成します。さきほど作ったVPCとサブネットを割り当てていきます。事前に、Lambdaに割り当てるIAMロールに適切なポリシーをアタッチしておいてください。
Lambdaを作成
- マネージメントコンソールからLambdaを選択します
-
関数の作成をクリックし、適当な名前を入力し、ランタイムにPython3.7を選択し、関数の作成をクリックします
- テスト用のコードを書きます。DynamoDBから1レコード取得して返すだけのものです
import json import boto3 client = boto3.resource('dynamodb') def lambda_handler(event, context): table = client.Table(cloudformationで作成されたテーブル名) res = table.get_item(Key={ "id": 1 }) item = res['Item'] return item
- Lambdaの設定画面のネットワークの項目で「非VPC」となっているところをさきほど作ったVPC、サブネット、セキュリティーグループを選択します
- 保存をクリックします
これでVPC Lambdaが作成できました。
VPC エンドポイントなしで実行してみる
VPCエンドポイントなしで、実行してみます。
DynamoDBのテーブルに適当なデータを一行追加して、先ほど作ったVPC Lambdaを実行してみます。実行すると以下のように、Lambdaがタイムアウトしてエラーになりました。インターネットアクセスがないため、DynamoDBにアクセスできていないようです。
VPCエンドポイントを設定する
プライベートサブネットに配置したLambdaからDynamoDBにアクセスするためにVPCエンドポイントを作成します。
- マネージメントコンソールからVPCを選択します
-
左側のメニューからエンドポイントを選択します
-
エンドポイントの作成をクリックします
- エンドポイントのサービス名の中から
com.amazonaws.リージョン名.dynamodb
を選択します
- VPC欄に先ほど作ったVPCを選択します。ルートテーブル欄で、VPC Lambdaが割り当てられているプライベートサブネットのルートテーブルを選択します
- エンドポイントの作成をクリックします
簡単にエンドポイントを作成できました。
VPCエンドポイントありで実行してみる
VPCエンドポイントを作成しましたので、Lambdaを再度実行してみます。さきほどはタイムアウトになっていましたが、今回はDynamoDBからデータが取得されました。
まとめ
VPCエンドポイントにより、簡単にVPC LambdaからAWSリソースにアクセスすることができるようになりました。VPC LambdaからVPC外のAWSリソースにアクセスする場合に参考にしてみてください。